#include <iostream>

using namespace std;

class HasPtr;

class U_Ptr
{
    friend class HasPtr;
    int *ip;
    size_t use;
    U_Ptr(int *p):ip(p), use(1)
    {

    }
    ~U_Ptr()
    {
        delete ip;
    }
};

class HasPtr
{
private:
    int m_i;
    U_Ptr *ptr;
public:
    HasPtr(int *p, int i):ptr(new U_Ptr(p)), m_i(i)
    {

    }
    HasPtr(const HasPtr &orig):ptr(orig.ptr), m_i(orig.m_i)
    {
        ++ptr->use;
    }
    ~HasPtr()
    {
        if(--ptr->use == 0)
            delete ptr;
    }

    HasPtr &operator=(const HasPtr& orig);

    int *get_ptr() const
    {
        return ptr->ip;
    }
    int get_val() const
    {
        return m_i;
    }

    void set_ptr(int *p)
    {
        ptr->ip = p;
    }

    void set_val(int i)
    {
        m_i = i;
    }

    int get_ptr_val() const
    {
        return *ptr->ip;
    }

    void set_ptr_val(int i)
    {
        *ptr->ip = i;
    }
};

HasPtr &HasPtr::operator=(const HasPtr& orig)
{
    ++orig.ptr->use;
    if(--ptr->use == 0)
        delete  ptr;

    ptr = orig.ptr;
    m_i = orig.m_i;

    return *this;
}
int main()
{
    int a = 3;
    int *p = &a;
    HasPtr hasptr(p, 3);
    hasptr.set_ptr_val(5);

    HasPtr hasptr2 = hasptr;
    cout << hasptr2.get_ptr_val() << endl;
    return 0;
}
